package cn.zyl.demo.common.tools;

import cn.zyl.demo.common.gif.AnimatedGifEncoder;
import cn.zyl.demo.common.gif.GifDecoder;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGEncodeParam;
import com.sun.image.codec.jpeg.JPEGImageEncoder;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;

/** ImageTool 工具类说明:
 * @author wsz
 * @date 2020-08-19
 * @version v1.0
 */
public class ImageTool {
    private ImageTool(){throw new IllegalAccessError("ImageTool");}
    /**
     * 把多张jpg图片合成一张
     * @param pic String[] 多个jpg文件名 包含路径
     * @param newPic String 生成的gif文件名 包含路径
     */
    public static void jpgToGif(String[] pic, String newPic) {
        try {
            AnimatedGifEncoder e = new AnimatedGifEncoder();
            e.setRepeat(0);
            e.start(newPic);
            BufferedImage[] src = new BufferedImage[pic.length];
            for (int i = 0; i < src.length; i++) {
                //设置播放的延迟时间
                e.setDelay(200);
                // 读入需要播放的jpg文件
                src[i] = ImageIO.read(new File(pic[i]));
                //添加到帧中
                e.addFrame(src[i]);
            }
            e.finish();
        } catch (Exception e) {
            System.out.println( "jpgToGif Failed:");
            e.printStackTrace();
        }
    }
    /**
     * 把gif图片按帧拆分成jpg图片
     * @param gifName String 小gif图片(路径+名称)
     * @param path String 生成小jpg图片的路径
     * @return String[] 返回生成小jpg图片的名称
     */
    public static String[] splitGif(String gifName,String path) {
        try {
            GifDecoder decoder = new GifDecoder();
            decoder.read(gifName);
            //得到frame的个数
            int n = decoder.getFrameCount();
            String[] subPic = new String[n];
            for (int i = 0; i < n; i++) {
                //得到帧
                BufferedImage frame = decoder.getFrame(i);
                //int delay = decoder.getDelay(i); //得到延迟时间
                //生成小的JPG文件
                subPic[i] = path + i + ".jpg";
                FileOutputStream out = new FileOutputStream(subPic[i]);
                ImageIO.write(frame, "jpeg", out);
                JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
                //存盘
                encoder.encode(frame);
                out.flush();
                out.close();
            }
            return subPic;
        } catch (Exception e) {
            System.out.println( "splitGif Failed!");
            e.printStackTrace();
            return null;
        }
    }
    /**
     * 根据提供的文字生成jpg图片
     * @param s String  文字
     * @param smallSize int  每个字的宽度和高度是一样的
     * @param bgColor Color  背景色
     * @param fontColor Color  字色
     * @param fontPath String 字体文件
     * @param jpgName String jpg图片名
     */
    public static void createJpgByFont(String s, int smallSize,Color bgColor,Color fontColor,String fontPath,String jpgName) {
        try {
            BufferedImage bufferedImage = new BufferedImage(s.length()*smallSize, smallSize,BufferedImage.TYPE_INT_RGB);
            Graphics2D g = bufferedImage.createGraphics();
            //背景色
            g.setColor(bgColor);
            //画一个矩形
            g.fillRect(0, 0, smallSize, smallSize);
            //去除锯齿(当设置的字体过大的时候,会出现锯齿)
            g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
            //字的颜色
            g.setColor(fontColor);
            //字体文件
            File file = new File(fontPath);
            //根据字体文件所在位置,创建新的字体对象(此语句在jdk1.5下面才支持)
            Font font = Font.createFont(Font.TRUETYPE_FONT, file);
            //font.deriveFont(float f)复制当前 Font 对象并应用新设置字体的大小
            g.setFont(font.deriveFont((float) smallSize));
            //在指定坐标除添加文字
            g.drawString(s,0, smallSize);
            g.dispose();
            //指定输出文件
            FileOutputStream out = new FileOutputStream(jpgName);
            JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
            JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(bufferedImage);
            param.setQuality(50f, true);
            //存盘
            encoder.encode(bufferedImage, param);
            out.flush();
            out.close();
        } catch (Exception e) {
            System.out.println( "createJpgByFont Failed!");
            e.printStackTrace();
        }
    }
    /**
     * 将多个小图片合成一张大jpg图  (小的jpg图片按照行列顺序平铺)
     * @param smallJpg ArrayList 一组小的jpg图片
     * @param bigWidth int 大图宽度
     * @param smallSize int  单个文字生成的小图的宽度和高度是一致的
     */
    public static void createBigJpg(ArrayList<ArrayList<String>> smallJpg, int bigWidth, int smallSize, Color bgColor , String picName) {
        try {
            //如果大图片的高度比小图片的高度还小 直接返回
            if (bigWidth < smallSize) { return; }
            //每行放置的字数
            int colCount = bigWidth / smallSize;
            //左边距
            int leftMargin = (int) ((bigWidth - colCount * smallSize) / 2f);
            //小图行数
            int rowCount = smallJpg.size();
            //每列中间不留空隙，只留左右边距
            int setHeight = smallSize * rowCount ;
            //按照大图片宽高绘制一个背景图片
            BufferedImage bufImage = new BufferedImage(bigWidth, setHeight, BufferedImage.TYPE_INT_RGB);
            Graphics2D g = bufImage.createGraphics();
            //背景的颜色
            g.setColor(bgColor);
            g.fillRect(0, 0, bigWidth, setHeight);
            //纵坐标
            int y = 0;
            //遍历每行
            for (ArrayList<String> col : smallJpg) {
                //横坐标  可能会出现左边距
                int x = leftMargin;
                for (String jpgName : col) {
                    ImageIcon icon = new ImageIcon(jpgName);
                    Image img = icon.getImage();
                    int imgWidth = img.getHeight(null);
                    g.drawImage(img, x, y, null);
                    x += imgWidth;
                }
                y += (smallSize);
            }
            g.dispose();
            //指定输出文件
            FileOutputStream out = new FileOutputStream(picName);
            //设置文件格式
            JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
            //从图片缓冲中读取
            JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(bufImage);
            param.setQuality(50f, true);
            //存盘
            encoder.encode(bufImage, param);
            out.flush();
            out.close();
        } catch (Exception e) {
            System.out.println( "createBigJPG Failed!");
            e.printStackTrace();
        }
    }
    /** 根据str,font的样式以及输出文件目录*/
    public static void createImage(String str, Font font, File outFile) throws Exception{
        //获取font的样式应用在str上的整个矩形
        Rectangle2D r=font.getStringBounds(str, new FontRenderContext(AffineTransform.getScaleInstance(1, 1),false,false));
        //获取单个字符的高度
        int unitHeight=(int)Math.floor(r.getHeight());
        //获取整个str用了font样式的宽度这里用四舍五入后+1保证宽度绝对能容纳这个字符串作为图片的宽度
        int width=(int)Math.round(r.getWidth())+1;
        //把单个字符的高度+3保证高度绝对能容纳字符串作为图片的高度
        int height=unitHeight+3;
        //创建图片
        BufferedImage image=new BufferedImage(width,height,BufferedImage.TYPE_INT_BGR);
        Graphics g=image.getGraphics();
        g.setColor(Color.WHITE);
        //先用白色填充整张图片,也就是背景
        g.fillRect(0, 0, width, height);
        //在换成黑色
        g.setColor(Color.black);
        //设置画笔字体
        g.setFont(font);
        //画出字符串
        g.drawString(str, 0, font.getSize());
        g.dispose();
        //输出png图片
        ImageIO.write(image, "png", outFile);
    }
    /** 多个图片叠加 */
    public static void combineImage(List<String> urlList, int width, int height, String destPath, String imgFormat) throws IOException {
        BufferedImage combinedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        Graphics g = combinedImage.getGraphics();
        URL url;URLConnection conn;InputStream in;BufferedImage image;
        for (String urlStr : urlList) {
            url = new URL(urlStr);
            conn = url.openConnection();
            conn.setReadTimeout(10 * 1000);
            in = conn.getInputStream();
            image = ImageIO.read(in);
            g.drawImage(image, 0, 0, width, height, null);
        }
        ImageIO.write(combinedImage, imgFormat, new File(destPath));
    }
    /**
     * 多图片转gif
     * @param imageList 图片流
     * @param outputPath 目标路径
     * @throws IOException 异常
     */
    static void imagesToGif(List<BufferedImage> imageList, String outputPath) throws IOException {
        // 拆分一帧一帧的压缩之后合成
        AnimatedGifEncoder encoder = new AnimatedGifEncoder();
        encoder.start(outputPath);
        encoder.setRepeat(0);
        for (BufferedImage bufferedImage :
                imageList) {
            encoder.setDelay(100);
            int height = bufferedImage.getHeight();
            int width = bufferedImage.getWidth();
            BufferedImage zoomImage = new BufferedImage(width, height, 3);
            Image image = bufferedImage.getScaledInstance(width, height, Image.SCALE_SMOOTH);
            Graphics gc = zoomImage.getGraphics();
            gc.setColor(Color.WHITE);
            gc.drawImage(image, 0, 0, null);
            encoder.addFrame(zoomImage);
        }
        encoder.finish();
        File outFile = new File(outputPath);
        BufferedImage image = ImageIO.read(outFile);
        ImageIO.write(image, outFile.getName(), outFile);
    }

    /**
     * Gif转图片集
     * @param imagePath gif路径
     * @param outputDirPath 图片集路径
     * @throws IOException 异常
     */
    static void gifToImages(String imagePath,String outputDirPath) throws IOException {
        GifDecoder decoder = new GifDecoder();
        int status = decoder.read(imagePath);
        if (status != GifDecoder.STATUS_OK) {
            throw new IOException("read image " + imagePath + " error!");
        }
        for (int i = 0; i < decoder.getFrameCount();i++) {
            // 获取每帧BufferedImage流
            BufferedImage bufferedImage = decoder.getFrame(i);
            File outFile = new File(outputDirPath + i + ".png");
            ImageIO.write(bufferedImage, "png", outFile);
        }
    }

    /**
     * 视频倒放
     * @param imagePath gif图片路径
     * @param outputPath 输出路径
     * @throws IOException 异常
     */
    public static void reverseGif(String imagePath,String outputPath) throws IOException {
        GifDecoder decoder = new GifDecoder();
        int status = decoder.read(imagePath);
        if (status != GifDecoder.STATUS_OK) {
            throw new IOException("read image " + imagePath + " error!");
        }
        // 拆分一帧一帧的压缩之后合成
        AnimatedGifEncoder encoder = new AnimatedGifEncoder();
        encoder.start(outputPath);
        encoder.setRepeat(decoder.getLoopCount());
        for (int i = decoder.getFrameCount() -1; i >= 0; i--) {
            // 设置播放延迟时间
            encoder.setDelay(decoder.getDelay(i));
            // 获取每帧BufferedImage流
            BufferedImage bufferedImage = decoder.getFrame(i);
            int height = bufferedImage.getHeight();
            int width = bufferedImage.getWidth();
            BufferedImage zoomImage = new BufferedImage(width, height, bufferedImage.getType());
            Image image = bufferedImage.getScaledInstance(width, height, Image.SCALE_SMOOTH);
            Graphics gc = zoomImage.getGraphics();
            gc.setColor(Color.WHITE);
            gc.drawImage(image, 0, 0, null);
            encoder.addFrame(zoomImage);
        }
        encoder.finish();
        File outFile = new File(outputPath);
        BufferedImage image = ImageIO.read(outFile);
        ImageIO.write(image, outFile.getName(), outFile);
    }
    public static void main(String[] args) {
        //TODO 图片工具优化-增减函数
    }
}